<?php

class Core_Error
{
    public static $found = false;

    public static function header()
    {
        if (!headers_sent()) {
            header('HTTP/1.0 500 Internal Server Error');
        }
    }

    public static function fatal()
    {
        if ($e = error_get_last()) {
            Error::exception(new ErrorException($e['message'], $e['type'], 0, $e['file'], $e['line']));
        }
    }

    public static function handler($code, $error, $file = 0, $line = 0)
    {
        // Ignore errors less than the current error setting
        if ((error_reporting() & $code) === 0) {
            return true;
        }

        Com_Log::write('error', "[$code] $error [$file] ($line)");

        self::$found = true;
        self::header();

        include template('system/error');

        return true;
    }

    public static function exception(Exception $e)
    {
        self::$found = true;

        // If the view fails, at least we can print this message!
        $message = "{$e->getMessage()} [{$e->getFile()}] ({$e->getLine()})";

        try {
            Com_Log::write('exception', $message);
            self::header();

            include template('system/exception');

        } catch (\Exception $e) {
            print $message;
        }

        exit(1);
    }

    /**
     * Fetch and HTML highlight serveral lines of a file.
     *
     * @param string $file to open
     * @param integer $number of line to highlight
     * @param integer $padding of lines on both side
     * @return string
     */
    public static function source($file, $number, $padding = 5)
    {
        // Get lines from file
        $lines = array_slice(file($file), $number - $padding - 1, $padding * 2 + 1, 1);

        $html = '';
        foreach ($lines as $i => $line) {
            $html .= '<b>' . sprintf('%' . mb_strlen($number + $padding) . 'd', $i + 1) . '</b> '
                    . ($i + 1 == $number ? '<em>' . htmlspecialchars($line) . '</em>' : htmlspecialchars($line));
        }
        return $html;
    }

    /**
     * Fetch a backtrace of the code
     *
     * @param int $offset to start from
     * @param int $limit of levels to collect
     * @return array
     */
    public static function backtrace($offset, $limit = 5)
    {
        $trace = array_slice(debug_backtrace(), $offset, $limit);

        foreach ($trace as $i => &$v) {
            if (!isset($v['file'])) {
                unset($trace[$i]);
                continue;
            }
            $v['source'] = self::source($v['file'], $v['line']);
        }

        return $trace;
    }
}